#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<fcntl.h>


#define  RM      "rm"
#define  RM_R    "rm -r"
#define  LS      "ls"
#define  LS_L    "ls -l"
#define  LS_L_C  "ls -l -color"
#define  MKDIR   "mkdir"
#define  GET     "get"
#define  UP      "up"
#define  EXIT    "exit"

char* get_cmd(char buff[],char* myargv[])
{
	if(buff==NULL || myargv==NULL) return NULL;

	int i=0;
	char *s=strtok(buff," ");
	while(s!=NULL)
	{
		myargv[i++]=s;
		s=strtok(NULL," ");
	}
	return myargv[0];//返回命令
}

int cmd_test(char* myargv[])
{
	if(myargv==NULL) return -1;

	FILE* fp=fopen("my.conf","r");
	if(NULL==fp) return -1;

	int index=0;
	while(1)
	{
		char buff[128]={0};
		if(NULL==fgets(buff,127,fp)) break;

		++index;
		if(strncmp(buff,"#",1)==0 || strncmp(buff,"\n",1)==0)
		{
			continue;
		}

		buff[strlen(buff)-1]=0;//去掉\n

		if(strncmp(buff,RM,strlen(RM))==0  && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
		else if(strncmp(buff,RM_R,strlen(RM_R))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
		else if(strncmp(buff,LS,strlen(LS))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
        else if(strncmp(buff,LS_L,strlen(LS_L))==0&& strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
        else if(strncmp(buff,LS_L_C,strlen(LS_L_C))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
        else if(strncmp(buff,MKDIR,strlen(MKDIR))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
        else if(strncmp(buff,GET,strlen(GET))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
        else if(strncmp(buff,UP,strlen(UP))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
        else if(strncmp(buff,EXIT,strlen(EXIT))==0 && strncmp(myargv[0],buff,sizeof(myargv[0]))==0)
		{
			return 0;
		}
		else
		{
			continue;
		}
	}
	fclose(fp);

	return -1;
}

void recv_file(int c,char* filename,char* strcmd)
{
	if(filename==NULL || strcmd==NULL)
	{
		printf("没有文件名，请重新输入\n");
		return;
	}

	send(c,strcmd,strlen(strcmd),0);//get a.c

	char buff[64]={0};
	int num=recv(c,buff,64,0);
	if(num<=0)
	{
		printf("ser closse\n");
		return;
	}

	if(strncmp(buff,"ok#",3)!=0)
	{
		printf("文件不存在或没权限\n");
		return;
	}

	printf("下载的文件：%s，大小为%s\n",filename,buff+3);

	int filesize=atoi(buff+3);

	int fd=open(filename,O_WRONLY|O_CREAT,0600);
	if(-1==fd)
	{
		send(c,"err",3,0);
		return;
	}
	send(c,"ok#",3,0);

	//接受
	char data[1024]={0};
	int curr_size=0;
	while(1)
	{
		num = recv(c,data,1024,0);
		if(num<=0)
		{
			printf("ser close\n");
			break;
		}

		write(fd,data,num);

		curr_size+=num;
		double f=curr_size * 100.0 / filesize;
		printf("下载进度：%.2f\r",f);

		if(curr_size>=filesize)
		{
			break;
		}
	}
	printf("\n");
	close(fd);
}

void send_file(int c,char* filename,char *strcmd)
{
	if(filename==NULL || strcmd==NULL)
	{
		printf("文件名不能为空\n");
		return;
	}

	int fd=open(filename,O_RDONLY);
	if(-1==fd)
	{
		printf("文件不存在或没权限\n");
		return;
	}

	send(c,strcmd,strlen(strcmd),0);//up a.c

	char buff[64]={0};
	int num=recv(c,buff,64,0);
	if(num<=0)
	{
		printf("ser close\n");
		return;
	}

	if(strncmp(buff,"ok",2)!=0)
	{
		printf("文件已存在,recv=%s\n",buff);
		return;
	}

	int filesize=lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);

	char tmp_buff[64]={0};
	sprintf(tmp_buff,"up#%d",filesize);
	send(c,tmp_buff,strlen(tmp_buff),0);

	num=recv(c,buff,64,0);
	if(num<=0)
	{
		printf("ser close\n");
		return;
	}
	if(strncmp(buff,"ok",2)!=0)
	{
		printf("不可上传\n");
		return;
	}

	char data_buff[1024]={0};
	while( (num=read(fd,data_buff,1024)) > 0)
	{
		send(c,data_buff,num,0);
	}

	
	num=recv(c,buff,64,0);
	if(num<=0)
	{
		printf("ser close\n");
		return;
	}
	if(strncmp(buff,"ok",2)==0)
	{
		printf("上传成功\n");
	}
	
	close(fd);
	return;

}
int main()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd!=-1);

	struct sockaddr_in saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
	saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res!=-1);

	while(1)
	{
    	char buff[128]={0};
    	printf("Connect:>>");
		fflush(stdout);

    	fgets(buff,128,stdin);
		buff[strlen(buff)-1]=0;//去掉\n
    	
		char buff_copy[128]={0};//buff的备份
		strcpy(buff_copy,buff);

		//解析buff
		char *myargv[10]={0};
		char *cmd=get_cmd(buff,myargv);
		if(NULL==cmd)
		{
			continue;
		}

		if(strcmp(cmd,"exit")==0)
		{
			break;
		}
		else if(strcmp(cmd,"get")==0)
		{
			//load
			recv_file(sockfd,myargv[1],buff_copy);
		}
		else if(strcmp(cmd,"up")==0)
		{
			//upload
			send_file(sockfd,myargv[1],buff_copy);
		}
		else
		{
			//检测命令是否可行
			if(-1==cmd_test(myargv))
			{
                printf("命令不可行\n");
				//break;
			}
			else
            {
                //执行命令
        			send(sockfd,buff_copy,strlen(buff_copy),0);
        			char recv_buff[1024]={0};
        			int num=recv(sockfd,recv_buff,1023,0);
        			if(num<=0)
        			{
        				printf("ser close\n");
        				break;
        			}
        			if(strncmp(recv_buff,"ok#",3)==0)
        			{
        				printf("%s\n",recv_buff+3);
        			}
        			else 
        			{
        				printf("cmd work filed\n");//执行失败
        			}
             }
		}
	}
	
	close(sockfd);
}
